package cn.hollis.nft.turbo.order.facade;

import cn.hollis.nft.turbo.api.collection.request.CollectionSaleRequest;
import cn.hollis.nft.turbo.api.collection.response.CollectionSaleResponse;
import cn.hollis.nft.turbo.api.collection.service.CollectionFacadeService;
import cn.hollis.nft.turbo.api.order.service.OrderFacadeService;
import cn.hollis.nft.turbo.api.order.constant.OrderErrorCode;
import cn.hollis.nft.turbo.api.order.model.TradeOrderVO;
import cn.hollis.nft.turbo.api.order.request.*;
import cn.hollis.nft.turbo.api.order.response.OrderResponse;
import cn.hollis.nft.turbo.api.user.constant.UserType;
import cn.hollis.nft.turbo.api.user.request.UserQueryRequest;
import cn.hollis.nft.turbo.api.user.response.UserQueryResponse;
import cn.hollis.nft.turbo.api.user.response.data.UserInfo;
import cn.hollis.nft.turbo.api.user.service.UserFacadeService;
import cn.hollis.nft.turbo.base.response.PageResponse;
import cn.hollis.nft.turbo.base.response.SingleResponse;
import cn.hollis.nft.turbo.lock.DistributeLock;
import cn.hollis.nft.turbo.order.domain.entity.TradeOrder;
import cn.hollis.nft.turbo.order.domain.entity.TradeOrderStream;
import cn.hollis.nft.turbo.order.domain.entity.convertor.TradeOrderConvertor;
import cn.hollis.nft.turbo.order.domain.exception.OrderException;
import cn.hollis.nft.turbo.order.domain.service.OrderManagerService;
import cn.hollis.nft.turbo.order.domain.service.OrderReadService;
import cn.hollis.nft.turbo.order.domain.validator.OrderCreateValidator;
import cn.hollis.nft.turbo.order.wrapper.InventoryWrapperService;
import cn.hollis.nft.turbo.rpc.facade.Facade;
import cn.hollis.turbo.stream.producer.StreamProducer;
import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import lombok.extern.slf4j.Slf4j;
import org.apache.dubbo.config.annotation.DubboService;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;

import java.util.List;

import static cn.hollis.nft.turbo.api.order.constant.OrderErrorCode.ORDER_CREATE_VALID_FAILED;

@DubboService(version = "1.0.0")
@Slf4j
public class OrderFacadeServiceImpl implements OrderFacadeService {
    @Autowired
    private OrderManagerService orderService;

    @Autowired
    private StreamProducer streamProducer;

    @Autowired
    private OrderReadService orderReadService;


    @Autowired
    private UserFacadeService userFacadeService;

    @Autowired
    private CollectionFacadeService collectionFacadeService;

    @Autowired
    private OrderCreateValidator orderValidatorChain;

    @Autowired
    private InventoryWrapperService inventoryWrapperService;

    @Facade
    @DistributeLock(keyExpression = "#request.identifier", scene = "ORDER_CREATE")
    @Override
    public OrderResponse create(OrderCreateRequest request) {
        log.info("----订单创建业务流程，检验请求参数OrderCreateRequest:{}",request);
        try {
            orderValidatorChain.validate(request);
        } catch (OrderException e) {
            return new OrderResponse.OrderResponseBuilder().buildFail(ORDER_CREATE_VALID_FAILED.getCode(), e.getErrorCode().getMessage());
        }

        log.info("----订单创建业务流程，开始预减库存:{}",request);
        Boolean preDeductResult = inventoryWrapperService.preDeduct(request);
      //  Boolean preDeductResult = true;
        log.info("----订单创建业务流程，预减库存结果:{}",preDeductResult==true?"success":"failed");
        if (preDeductResult) {

            return orderService.create(request);
        }
        throw new OrderException(OrderErrorCode.INVENTORY_DEDUCT_FAILED);
    }
    /**
     * 取消订单
     *
     * @param request
     * @return
     */    @Override
    @Facade
    public OrderResponse cancel(OrderCancelRequest request) {
        return sendTransactionMsgForClose(request);
    }


    /**
     * 订单超时
     *
     * @param request
     * @return
     */
    @Override
    @Facade
    public OrderResponse timeout(OrderTimeoutRequest request) {
        return sendTransactionMsgForClose(request);
    }
    /**
     * 订单确认
     *
     * @param request
     * @return
     */
    @Override
    @Facade
    public OrderResponse confirm(OrderConfirmRequest request) {

        TradeOrder existOrder = orderReadService.getOrder(request.getOrderId());

        CollectionSaleRequest collectionSaleRequest = new CollectionSaleRequest();
        collectionSaleRequest.setUserId(existOrder.getBuyerId());
        collectionSaleRequest.setCollectionId(Long.valueOf(existOrder.getGoodsId()));
        collectionSaleRequest.setIdentifier(request.getIdentifier());
        collectionSaleRequest.setQuantity((long) existOrder.getItemCount());

        log.info("----订单创建业务流程，进行trySale,collectionSaleRequest:{}",collectionSaleRequest);
        CollectionSaleResponse response = collectionFacadeService.trySale(collectionSaleRequest);

        if (response.getSuccess()) {
            log.info("----订单创建业务流程，订单状态更新为CONFIRM}");
            return orderService.confirm(request);
        }


        return new OrderResponse.OrderResponseBuilder().orderId(existOrder.getOrderId()).buildFail(response.getResponseCode(), response.getResponseMessage());
    }


    private OrderResponse sendTransactionMsgForClose(BaseOrderUpdateRequest request) {
        boolean result = streamProducer.send("orderClose-out-0", null, JSON.toJSONString(request), "CLOSE_TYPE", request.getOrderEvent().name());
        log.info("----订单取消业务流程，发送消息到rocketMQ,消息体:{},发送结果:{}", JSON.toJSONString(request),result);
        OrderResponse orderResponse = new OrderResponse();
        if (result) {
            orderResponse.setSuccess(true);
        } else {
            orderResponse.setSuccess(false);
        }
        return orderResponse;
    }

    @Override
    public OrderResponse pay(OrderPayRequest request) {
        OrderResponse response = orderService.pay(request);
        if (!response.getSuccess()) {
            TradeOrder existOrder = orderReadService.getOrder(request.getOrderId());
            if (existOrder != null && existOrder.isPaid()) {
                if (existOrder.getPayStreamId().equals(request.getPayStreamId()) && existOrder.getPayChannel() == request.getPayChannel()) {
                    return new OrderResponse.OrderResponseBuilder().orderId(existOrder.getOrderId()).buildSuccess();
                } else {
                    return new OrderResponse.OrderResponseBuilder().orderId(existOrder.getOrderId()).buildFail(OrderErrorCode.ORDER_ALREADY_PAID.getCode(), OrderErrorCode.ORDER_ALREADY_PAID.getMessage());
                }
            }
        }
        return response;
    }

    @Override
    public SingleResponse<TradeOrderVO> getTradeOrder(String orderId) {
        return SingleResponse.of(TradeOrderConvertor.INSTANCE.mapToVo(orderReadService.getOrder(orderId)));
    }

    @Override
    public SingleResponse<TradeOrderVO> getTradeOrder(String orderId, String userId) {
        return SingleResponse.of(TradeOrderConvertor.INSTANCE.mapToVo(orderReadService.getOrder(orderId, userId)));
    }

    @Override
    public PageResponse<TradeOrderVO> pageQuery(OrderPageQueryRequest request) {
        Page<TradeOrder> tradeOrderPage = orderReadService.pageQueryByState(request.getBuyerId(), request.getState(), request.getCurrentPage(), request.getPageSize());
        List<TradeOrderVO> tradeOrderVos = TradeOrderConvertor.INSTANCE.mapToVo(tradeOrderPage.getRecords());
        tradeOrderVos.forEach(tradeOrderVO -> tradeOrderVO.setSellerName(getSellerName(tradeOrderVO)));
       return PageResponse.of(tradeOrderVos, (int) tradeOrderPage.getTotal(), request.getPageSize(), request.getCurrentPage());
    }

    @Override
    public OrderResponse createAndConfirm(OrderCreateAndConfirmRequest request) {
        log.info("----订单创建业务流程(RoacketMQ),参数校验,request:{}",request);
        try {
            orderValidatorChain.validate(request);
        } catch (OrderException e) {
            return new OrderResponse.OrderResponseBuilder().buildFail(ORDER_CREATE_VALID_FAILED.getCode(), e.getErrorCode().getMessage());
        }

        CollectionSaleRequest collectionSaleRequest = new CollectionSaleRequest(request);
        log.info("----订单创建业务流程(RoacketMQ),预扣减库存trySaleWithoutHint,collectionSaleRequest:{}",collectionSaleRequest);
        CollectionSaleResponse response = collectionFacadeService.trySaleWithoutHint(collectionSaleRequest);

        if (!response.getSuccess()) {
            return new OrderResponse.OrderResponseBuilder().buildFail(response.getResponseMessage(), response.getResponseCode());
        }

        return orderService.createAndConfirm(request);
    }

    private String getSellerName(TradeOrderVO tradeOrderVO) {
        if (tradeOrderVO.getSellerType() == UserType.PLATFORM) {
            return "平台";
        }
        UserQueryRequest userQueryRequest = new UserQueryRequest(Long.valueOf(tradeOrderVO.getSellerId()));

        UserQueryResponse<UserInfo> userQueryResponse = userFacadeService.query(userQueryRequest);
        if (userQueryResponse.getSuccess()) {
            return userQueryResponse.getData().getNickName();
        }

        return "-";
    }

}
